package org.go.threadpool;

import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;

import org.go.expcetion.SchedulerConfigException;
import org.go.trigger.CronExpression;
import org.go.trigger.Trigger;
import org.go.work.Work;

/**
 *
 * <p>
 * <code>ThreadPool</code> implementation instances should ideally be made
 * for the sole use of Go.  Most importantly, when the method
 * <code>blockForAvailableThreads()</code> returns a value of 1 or greater,
 * there must still be at least one available thread in the pool when the
 * method <code>runInThread(Runnable)</code> is called a few moments (or
 * many moments) later.  If this assumption does not hold true, it may
 * result in extra JobStore queries and updates, and if clustering features
 * are being used, it may result in greater imballance of load.
 * </p>
 *
 * @see org.go.threadpool.MyScheduledThreadPoolExecutor
 *
 * @author hejie
 */
public interface GoThreadPool {
	/**
	 * <p>
	 * Determines the number of threads that are currently available in in
	 * the pool.  Useful for determining the number of times
	 * <code>runInThread(Runnable)</code> can be called before returning
	 * false.
	 * </p>
	 *
	 * <p>The implementation of this method should block until there is at
	 * least one available thread.</p>
	 *
	 * @return the number of currently available threads
	 */
	int blockForAvailableThreads();

	/**
	 * <p>Get the current number of core threads in the <code>ThreadPool</code>.</p>
	 *
	 * @return the core pool size
	 */
	int getCorePoolSize();

	/**
	 * Gets the pool id.
	 *
	 * @return the pool id
	 */
	String getPoolId();

	/**
	 * Gets the pool id.
	 *
	 * @return the pool id
	 */
	String getThreadPoolId();

	/**
	 * <p>
	 * Must be called before the <code>ThreadPool</code> is
	 * used, in order to give the it a chance to initialize.
	 * </p>
	 * 
	 * <p>Typically called by the <code>SchedulerFactory</code>.</p>
	 *
	 * @throws SchedulerConfigException the scheduler config exception
	 */
	void initialize() throws SchedulerConfigException;

	/**
	 * Checks if is paused.
	 *
	 * @return true, if is paused
	 */
	boolean isPaused();

	/**
	 * Pause.
	 */
	void pause();

	/**
	 * Resume.
	 */
	void resume();

	/**
	 * <p>
	 * Execute the given <code>{@link java.lang.Runnable}</code> in the next
	 * available <code>Thread</code>.
	 * </p>
	 * 
	 * <p>
	 * The implementation of this interface should not throw exceptions unless
	 * there is a serious problem (i.e. a serious misconfiguration). If there
	 * are no immediately available threads <code>false</code> should be returned.
	 * </p>
	 *
	 * @param runnable the runnable
	 * @return true, if the runnable was assigned to run on a Thread.
	 */
	boolean runInThread(Runnable runnable);

	/**
	 * 
	 * @param command
	 * @param cronExpression
	 * @return
	 */
	ScheduledFuture<?> scheduleWithCronExp(Runnable command, CronExpression cronExpression);

	/**
	 * 
	 * @param command
	 * @param cronExpression
	 * @return
	 */
	ScheduledFuture<?> scheduleWithCronExp(Work command, Trigger trigger) throws Exception;

	/**
	 * Shutdown.
	 */
	void shutdown();

	/**
	 * <p>
	 * Called by the QuartzScheduler to inform the <code>ThreadPool</code>
	 * that it should free up all of it's resources because the scheduler is
	 * shutting down.
	 * </p>
	 *
	 * @param waitForJobsToComplete the wait for jobs to complete
	 */
	void shutdown(boolean waitForJobsToComplete);

	/**
	 * Shutdown now.
	 *
	 * @return the list
	 */
	List<Runnable> shutdownNow();

	/**
	 * 
	 * @param threadcount
	 */
	void setThreadCount(int threadcount);

	/**
	 * Submit.
	 *
	 * @param <T> the generic type
	 * @param task the task
	 * @return the future
	 */
	<T> Future<T> submit(Callable<T> task);
}
